home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / restore.c < prev    next >
C/C++ Source or Header  |  1993-01-23  |  22KB  |  915 lines

  1. /*    SCCS Id: @(#)restore.c    3.1    93/01/23    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6. #include "lev.h"
  7. #include "termcap.h" /* for TERMLIB and ASCIIGRAPH */
  8.  
  9. #ifdef MICRO
  10. extern int dotcnt;    /* shared with save */
  11. #endif
  12.  
  13. #ifdef ZEROCOMP
  14. static int NDECL(mgetc);
  15. #endif
  16. static void NDECL(find_lev_obj);
  17. #ifndef NO_SIGNAL
  18. static void NDECL(inven_inuse);
  19. #endif
  20. static void FDECL(restlevchn, (int));
  21. static void FDECL(restdamage, (int,BOOLEAN_P));
  22. static struct obj * FDECL(restobjchn, (int,BOOLEAN_P));
  23. static struct monst * FDECL(restmonchn, (int,BOOLEAN_P));
  24. static void FDECL(restgenoinfo, (int));
  25. static boolean FDECL(restgamestate, (int, unsigned int *));
  26. static int FDECL(restlevelfile, (int,XCHAR_P));
  27.  
  28. #ifdef MULDGN
  29. #include "quest.h"
  30. #endif
  31.  
  32. boolean restoring = FALSE;
  33. #ifdef TUTTI_FRUTTI
  34. static struct fruit NEARDATA *oldfruit;
  35. #endif
  36. static long NEARDATA omoves;
  37.  
  38. /* Recalculate level.objects[x][y], since this info was not saved. */
  39. static void
  40. find_lev_obj()
  41. {
  42.     register struct obj *fobjtmp = (struct obj *)0;
  43.     register struct obj *otmp;
  44.     int x,y;
  45.  
  46.     for(x=0; x<COLNO; x++) for(y=0; y<ROWNO; y++)
  47.         level.objects[x][y] = (struct obj *)0;
  48.  
  49.     /* Reverse the entire fobj chain, which is necessary so that we can
  50.      * place the objects in the proper order.
  51.      */
  52.     while ((otmp = fobj) != 0) {
  53.         fobj = otmp->nobj;
  54.         otmp->nobj = fobjtmp;
  55.         fobjtmp = otmp;
  56.     }
  57.     /* Set level.objects (as well as reversing the chain back again) */
  58.     while ((otmp = fobjtmp) != 0) {
  59.         place_object(otmp, otmp->ox, otmp->oy);
  60.         fobjtmp = otmp->nobj;
  61.         otmp->nobj = fobj;
  62.         fobj = otmp;
  63.     }
  64. }
  65.  
  66. #ifndef NO_SIGNAL
  67. static void
  68. inven_inuse()
  69. /* Things that were marked "in_use" when the game was saved (ex. via the
  70.  * infamous "HUP" cheat) get used up here.
  71.  */
  72. {
  73.     register struct obj *otmp, *otmp2;
  74.  
  75.     for(otmp = invent; otmp; otmp = otmp2) {
  76.         otmp2 = otmp->nobj;
  77.         if(otmp->in_use) {
  78.             /* in_use and oldcorpse share a bit, but we don't
  79.              * want nasty messages for old corpses --
  80.              * remove_cadavers() will clean them up nicely
  81.              */
  82.             if (otmp->otyp == CORPSE &&
  83.                     mons[otmp->corpsenm].mlet == S_TROLL)
  84.                 continue;
  85.             pline("Finishing off %s...", xname(otmp));
  86.             useup(otmp);
  87.         }
  88.     }
  89. }
  90. #endif
  91.  
  92. static void
  93. restlevchn(fd)
  94. register int fd;
  95. {
  96.     int cnt;
  97.     s_level    *tmplev, *x;
  98.  
  99.     sp_levchn = (s_level *) 0;
  100.     mread(fd, (genericptr_t) &cnt, sizeof(int));
  101.     for(; cnt > 0; cnt--) {
  102.  
  103.         tmplev = (s_level *)alloc(sizeof(s_level));
  104.         mread(fd, (genericptr_t) tmplev, sizeof(s_level));
  105.         if(!sp_levchn) sp_levchn = tmplev;
  106.         else {
  107.  
  108.         for(x = sp_levchn; x->next; x = x->next);
  109.         x->next = tmplev;
  110.         }
  111.         tmplev->next = (s_level *)0;
  112.     }
  113. }
  114.  
  115. static void
  116. restdamage(fd, ghostly)
  117. int fd;
  118. boolean ghostly;
  119. {
  120.     int counter;
  121.     struct damage *tmp_dam;
  122.  
  123.     mread(fd, (genericptr_t) &counter, sizeof(counter));
  124.     if (!counter)
  125.         return;
  126.     tmp_dam = (struct damage *)alloc(sizeof(struct damage));
  127.     while (1) {
  128.         char damaged_shops[5], *shp = NULL;
  129.  
  130.         mread(fd, (genericptr_t) tmp_dam, sizeof(*tmp_dam));
  131.         if (ghostly)
  132.         tmp_dam->when += (monstermoves - omoves);
  133.         Strcpy(damaged_shops,
  134.            in_rooms(tmp_dam->place.x, tmp_dam->place.y, SHOPBASE));
  135.         if (u.uz.dlevel) {
  136.         /* when restoring, there are two passes over the current
  137.          * level.  the first time, u.uz isn't set, so neither is
  138.          * shop_keeper().  just wait and process the damage on
  139.          * the second pass.
  140.          */
  141.         for (shp = damaged_shops; *shp; shp++) {
  142.             struct monst *shkp = shop_keeper(*shp);
  143.  
  144.             if (shkp && inhishop(shkp) && repair_damage(shkp, tmp_dam))
  145.             break;
  146.         }
  147.         }
  148.         if (!shp || !*shp) {
  149.         tmp_dam->next = level.damagelist;
  150.         level.damagelist = tmp_dam;
  151.         tmp_dam = (struct damage *)alloc(sizeof(*tmp_dam));
  152.         }
  153.         if (!(--counter)) {
  154.         free((genericptr_t)tmp_dam);
  155.         return;
  156.         }
  157.     }
  158. }
  159.  
  160. static struct obj *
  161. restobjchn(fd, ghostly)
  162. register int fd;
  163. boolean ghostly;
  164. {
  165.     register struct obj *otmp, *otmp2;
  166.     register struct obj *first = (struct obj *)0;
  167. #ifdef TUTTI_FRUTTI
  168.     register struct fruit *oldf;
  169. #endif
  170.     int xl;
  171.  
  172. #if defined(LINT) || defined(GCC_WARN)
  173.     /* suppress "used before set" warning from lint */
  174.     otmp2 = 0;
  175. #endif
  176.     while(1) {
  177.         mread(fd, (genericptr_t) &xl, sizeof(xl));
  178.         if(xl == -1) break;
  179.         otmp = newobj(xl);
  180.         if(!first) first = otmp;
  181.         else otmp2->nobj = otmp;
  182.         mread(fd, (genericptr_t) otmp,
  183.                     (unsigned) xl + sizeof(struct obj));
  184.         if(!otmp->o_id) otmp->o_id = flags.ident++;
  185. #ifdef TUTTI_FRUTTI
  186.         if(ghostly && otmp->otyp == SLIME_MOLD) {
  187.             for(oldf=oldfruit; oldf; oldf=oldf->nextf)
  188.                 if (oldf->fid == otmp->spe) break;
  189.             if(!oldf) impossible("no old fruit?");
  190.             else otmp->spe = fruitadd(oldf->fname);
  191.         }
  192. #endif
  193.         /* Ghost levels get object age shifted from old player's clock
  194.          * to new player's clock.  Assumption: new player arrived
  195.          * immediately after old player died.
  196.          */
  197.         if (ghostly && otmp->otyp != OIL_LAMP
  198.                 && otmp->otyp != BRASS_LANTERN
  199.                 && otmp->otyp != CANDELABRUM_OF_INVOCATION
  200.                 && !Is_candle(otmp))
  201.             otmp->age = monstermoves-omoves+otmp->age;
  202.  
  203.         /* get contents of the container */
  204.         if (Is_container(otmp) || otmp->otyp == STATUE)
  205.             otmp->cobj = restobjchn(fd,ghostly);
  206.  
  207.         otmp2 = otmp;
  208.     }
  209.     if(first && otmp2->nobj){
  210.         impossible("Restobjchn: error reading objchn.");
  211.         otmp2->nobj = 0;
  212.     }
  213.  
  214.     return(first);
  215. }
  216.  
  217. static struct monst *
  218. restmonchn(fd, ghostly)
  219. register int fd;
  220. boolean ghostly;
  221. {
  222.     register struct monst *mtmp, *mtmp2;
  223.     register struct monst *first = (struct monst *)0;
  224.     int xl;
  225.     struct permonst *monbegin;
  226.     boolean moved;
  227.  
  228.     /* get the original base address */
  229.     mread(fd, (genericptr_t)&monbegin, sizeof(monbegin));
  230.     moved = (monbegin != mons);
  231.  
  232. #if defined(LINT) || defined(GCC_WARN)
  233.     /* suppress "used before set" warning from lint */
  234.     mtmp2 = 0;
  235. #endif
  236.     while(1) {
  237.         mread(fd, (genericptr_t) &xl, sizeof(xl));
  238.         if(xl == -1) break;
  239.         mtmp = newmonst(xl);
  240.         if(!first) first = mtmp;
  241.         else mtmp2->nmon = mtmp;
  242.         mread(fd, (genericptr_t) mtmp, (unsigned) xl + sizeof(struct monst));
  243.         if(!mtmp->m_id)
  244.             mtmp->m_id = flags.ident++;
  245.         if (moved && mtmp->data) {
  246.             int offset = mtmp->data - monbegin;    /*(ptrdiff_t)*/
  247.             mtmp->data = mons + offset;  /* new permonst location */
  248.         }
  249.         if(mtmp->minvent)
  250.             mtmp->minvent = restobjchn(fd, ghostly);
  251. #ifdef MUSE
  252.         if (mtmp->mw) mtmp->mw = mtmp->minvent;    /* wield 1st obj in inventory */
  253. #endif
  254.         if (mtmp->isshk) restshk(mtmp);
  255.  
  256.         mtmp2 = mtmp;
  257.     }
  258.     if(first && mtmp2->nmon){
  259.         impossible("Restmonchn: error reading monchn.");
  260.         mtmp2->nmon = 0;
  261.     }
  262.     return(first);
  263. }
  264.  
  265. static void
  266. restgenoinfo(fd)
  267. register int fd;
  268. {
  269.     register int i;
  270.     unsigned genolist[NUMMONS];
  271.  
  272.     mread(fd, (genericptr_t) genolist, sizeof(genolist));
  273.  
  274.     for (i = 0; i < NUMMONS; i++)
  275.         mons[i].geno = genolist[i];
  276. }
  277.  
  278. static
  279. boolean
  280. restgamestate(fd, mid)
  281. register int fd;
  282. unsigned int *mid;
  283. {
  284.     struct obj *otmp;
  285.     int tmp;        /* not a register ! */
  286.     struct flag oldflags;
  287. #ifdef TUTTI_FRUTTI
  288.     struct fruit *fruit;
  289. #endif
  290.  
  291.     invent = restobjchn(fd, FALSE);
  292.     migrating_objs = restobjchn(fd, FALSE);
  293.     migrating_mons = restmonchn(fd, FALSE);
  294.     restgenoinfo(fd);
  295.  
  296.     mread(fd, (genericptr_t) &tmp, sizeof tmp);
  297. #ifdef WIZARD
  298.     if(!wizard)
  299. #endif
  300.         if(tmp != getuid()) {        /* strange ... */
  301.         pline("Saved game was not yours.");
  302.         return(FALSE);
  303.         }
  304.  
  305.     oldflags = flags;
  306.     mread(fd, (genericptr_t) &flags, sizeof(struct flag));
  307.     /* Some config file and command line OPTIONS take precedence over
  308.      * those in save file.
  309.      */
  310. #ifdef TERMLIB
  311.     flags.DECgraphics = oldflags.DECgraphics;
  312. #endif
  313. #ifdef ASCIIGRAPH
  314.     flags.IBMgraphics = oldflags.IBMgraphics;
  315. #endif
  316. #ifdef MICRO
  317.     flags.rawio = oldflags.rawio;
  318.     flags.BIOS = oldflags.BIOS;
  319. #endif
  320. #ifdef TEXTCOLOR
  321.     flags.use_color = oldflags.use_color;
  322.     flags.hilite_pet = oldflags.hilite_pet;
  323. #endif
  324. #ifdef MAC_GRAPHICS_ENV
  325.     flags.MACgraphics = oldflags.MACgraphics;
  326.     flags.large_font = oldflags.large_font;
  327. #endif
  328.     /* these come from the current environment; ignore saved values */
  329.     flags.window_inited = oldflags.window_inited;
  330.     flags.msg_history = oldflags.msg_history;
  331.     flags.echo = oldflags.echo;
  332.     flags.cbreak = oldflags.cbreak;
  333.  
  334.     mread(fd, (genericptr_t) &u, sizeof(struct you));
  335.     if(u.uhp <= 0) {
  336.         You("were not healthy enough to survive restoration.");
  337.         /* wiz1_level.dlevel is used by mklev.c to see if lots of stuff is
  338.          * uninitialized, so we only have to set it and not the other stuff.
  339.          */
  340.         wiz1_level.dlevel = 0;
  341.         u.uz.dnum = 0;
  342.         u.uz.dlevel = 1;
  343.         return(FALSE);
  344.     }
  345.  
  346.     /* don't do this earlier to avoid complicating abort above */
  347.     for(otmp = invent; otmp; otmp = otmp->nobj)
  348.         if(otmp->owornmask)
  349.             setworn(otmp, otmp->owornmask);
  350.  
  351.     restore_dungeon(fd);
  352.     mread(fd, (genericptr_t) &inv_pos, sizeof inv_pos);
  353.     restlevchn(fd);
  354.     mread(fd, (genericptr_t) &moves, sizeof moves);
  355.     mread(fd, (genericptr_t) &monstermoves, sizeof monstermoves);
  356. #ifdef MULDGN
  357.     mread(fd, (genericptr_t) &quest_status, sizeof(struct q_score));
  358. #endif
  359.     mread(fd, (genericptr_t) spl_book,
  360.                 sizeof(struct spell) * (MAXSPELL + 1));
  361.     restore_artifacts(fd);
  362.     restore_oracles(fd);
  363.     if(u.ustuck)
  364.         mread(fd, (genericptr_t) mid, sizeof (*mid));
  365.     mread(fd, (genericptr_t) pl_character, sizeof pl_character);
  366.  
  367. #ifdef TUTTI_FRUTTI
  368.     mread(fd, (genericptr_t) pl_fruit, sizeof pl_fruit);
  369.     mread(fd, (genericptr_t) ¤t_fruit, sizeof current_fruit);
  370.     ffruit = 0;
  371.     while (fruit = newfruit(),
  372.            mread(fd, (genericptr_t)fruit, sizeof(struct fruit)),
  373.            fruit->fid) {
  374.         fruit->nextf = ffruit;
  375.         ffruit = fruit;
  376.     }
  377.     dealloc_fruit(fruit);
  378. #endif
  379.     restnames(fd);
  380.     restore_waterlevel(fd);
  381.     return(TRUE);
  382. }
  383.  
  384. /*ARGSUSED*/    /* fd used in MFLOPPY only */
  385. static int
  386. restlevelfile(fd, ltmp)
  387. register int fd;
  388. xchar ltmp;
  389. {
  390.     register int nfd;
  391.  
  392.     nfd = create_levelfile(ltmp);
  393.  
  394.     if (nfd < 0)    panic("Cannot open temp level %d!", ltmp);
  395. #ifdef MFLOPPY
  396.     if (!savelev(nfd, ltmp, COUNT_SAVE)) {
  397.  
  398.         /* The savelev can't proceed because the size required
  399.          * is greater than the available disk space.
  400.          */
  401.         pline("Not enough space on `%s' to restore your game.",
  402.             levels);
  403.  
  404.         /* Remove levels and bones that may have been created.
  405.          */
  406.         (void) close(nfd);
  407.         eraseall(levels, alllevels);
  408. # ifndef AMIGA
  409.         eraseall(levels, allbones);
  410.  
  411.         /* Perhaps the person would like to play without a
  412.          * RAMdisk.
  413.          */
  414.         if (ramdisk) {
  415.             /* PlaywoRAMdisk may not return, but if it does
  416.              * it is certain that ramdisk will be 0.
  417.              */
  418.             playwoRAMdisk();
  419.             /* Rewind save file and try again */
  420.             (void) lseek(fd, (off_t)0, 0);
  421.             return dorecover(fd);    /* 0 or 1 */
  422.         } else {
  423. # endif
  424.             pline("Be seeing you...");
  425.             terminate(0);
  426. # ifndef AMIGA
  427.         }
  428. # endif
  429.     }
  430. #endif
  431.     bufon(nfd);
  432.     savelev(nfd, ltmp, WRITE_SAVE | FREE_SAVE);
  433.     bclose(nfd);
  434.     return(2);
  435. }
  436.  
  437. int
  438. dorecover(fd)
  439. register int fd;
  440. {
  441.     unsigned int mid;        /* not a register */
  442.     xchar ltmp;
  443.     int rtmp;
  444.     struct obj *otmp;
  445.  
  446.     minit();    /* ZEROCOMP */
  447.     restoring = TRUE;
  448.     getlev(fd, 0, (xchar)0, FALSE);
  449.     if (!restgamestate(fd, &mid)) {
  450.         (void) close(fd);
  451.         (void) delete_savefile();
  452.         restoring = FALSE;
  453.         return(0);
  454.     }
  455. #ifdef INSURANCE
  456.     savestateinlock();
  457. #endif
  458.     rtmp = restlevelfile(fd, ledger_no(&u.uz));
  459.     if (rtmp < 2) return(rtmp);  /* dorecover called recursively */
  460.  
  461. #ifdef MICRO
  462. # ifdef AMIGA
  463.     {
  464.     extern winid WIN_BASE;
  465.     clear_nhwindow(WIN_BASE);    /* hack until there's a hook for this */
  466.     }
  467. # else
  468.     clear_nhwindow(WIN_MAP);
  469. # endif
  470.     clear_nhwindow(WIN_MESSAGE);
  471.     You("got as far as level %d in %s%s.",
  472.         depth(&u.uz), dungeons[u.uz.dnum].dname,
  473.         flags.debug ? " while in WIZARD mode" :
  474.         flags.explore ? " while in discovery mode" : "");
  475.     curs(WIN_MAP, 1, 1);
  476.     dotcnt = 0;
  477.     putstr(WIN_MAP, 0, "Restoring:");
  478. #endif
  479.     while(1) {
  480. #ifdef ZEROCOMP
  481.         if(mread(fd, (genericptr_t) <mp, sizeof ltmp) < 0)
  482. #else
  483.         if(read(fd, (genericptr_t) <mp, sizeof ltmp) != sizeof ltmp)
  484. #endif
  485.             break;
  486.         getlev(fd, 0, ltmp, FALSE);
  487. #ifdef MICRO
  488.         curs(WIN_MAP, 11 + dotcnt++, 1);
  489.         putstr(WIN_MAP, 0, ".");
  490. #endif
  491.         rtmp = restlevelfile(fd, ltmp);
  492.         if (rtmp < 2) return(rtmp);  /* dorecover called recursively */
  493.     }
  494.  
  495. #ifdef BSD
  496.     (void) lseek(fd, 0L, 0);
  497. #else
  498.     (void) lseek(fd, (off_t)0, 0);
  499. #endif
  500.     minit();    /* ZEROCOMP */
  501.     getlev(fd, 0, (xchar)0, FALSE);
  502.     (void) close(fd);
  503.  
  504. #if defined(WIZARD) || defined(EXPLORE_MODE)
  505.     if(
  506. # ifdef WIZARD
  507.        !wizard
  508. #  ifdef EXPLORE_MODE
  509.            &&
  510. #  endif
  511. # endif
  512. # ifdef EXPLORE_MODE
  513.               !discover
  514. # endif
  515.                 )
  516. #endif
  517.         (void) delete_savefile();
  518. #ifdef REINCARNATION
  519.     if (Is_rogue_level(&u.uz)) assign_rogue_graphics(TRUE);
  520. #endif
  521.     if(u.ustuck) {
  522.         register struct monst *mtmp;
  523.  
  524.         for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  525.             if(mtmp->m_id == mid) goto monfnd;
  526.         panic("Cannot find the monster ustuck.");
  527.     monfnd:
  528.         u.ustuck = mtmp;
  529.     }
  530. #ifdef MFLOPPY
  531.     gameDiskPrompt();
  532. #endif
  533.     max_rank_sz(); /* to recompute mrank_sz (botl.c) */
  534. #ifdef POLYSELF
  535.     set_uasmon();
  536. #endif
  537.     /* take care of iron ball & chain */
  538.     for(otmp = fobj; otmp; otmp = otmp->nobj)
  539.         if(otmp->owornmask)
  540.             setworn(otmp, otmp->owornmask);
  541. #ifndef NO_SIGNAL
  542.     /* in_use processing must be after:
  543.      *    + The inventory has been read so that freeinv() works.
  544.      *    + The current level has been restored so billing information
  545.      *    is available.
  546.      */
  547.     inven_inuse();
  548. #endif
  549. #ifdef MULDGN
  550.     load_qtlist();    /* re-load the quest text info */
  551. #endif
  552.     /* Set up the vision internals, after levl[] data is loaded */
  553.     /* but before docrt().                        */
  554.     vision_reset();
  555.     vision_full_recalc = 1;    /* recompute vision (not saved) */
  556.     docrt();
  557.     restoring = FALSE;
  558.     clear_nhwindow(WIN_MESSAGE);
  559.     return(1);
  560. }
  561.  
  562. void
  563. trickery()
  564. {
  565.     pline("Strange, this map is not as I remember it.");
  566.     pline("Somebody is trying some trickery here...");
  567.     pline("This game is void.");
  568.     done(TRICKED);
  569. }
  570.  
  571. void
  572. getlev(fd, pid, lev, ghostly)
  573. int fd, pid;
  574. xchar lev;
  575. boolean ghostly;
  576. {
  577.     register struct trap *trap;
  578.     register struct monst *mtmp;
  579.     branch *br;
  580.     int hpid;
  581.     xchar dlvl;
  582.     int x, y;
  583. #ifdef TOS
  584.     short tlev;
  585. #endif
  586.  
  587. #if defined(MSDOS) || defined(OS2)
  588.     setmode(fd, O_BINARY);
  589. #endif
  590. #ifdef TUTTI_FRUTTI
  591.     /* Load the old fruit info.  We have to do it first, so the
  592.      * information is available when restoring the objects.
  593.      */
  594.     if (ghostly) {
  595.         struct fruit *fruit;
  596.  
  597.         oldfruit = 0;
  598.         while (fruit = newfruit(),
  599.                mread(fd, (genericptr_t)fruit, sizeof(struct fruit)),
  600.                fruit->fid) {
  601.             fruit->nextf = oldfruit;
  602.             oldfruit = fruit;
  603.         }
  604.         dealloc_fruit(fruit);
  605.     }
  606. #endif
  607.  
  608.     /* First some sanity checks */
  609.     mread(fd, (genericptr_t) &hpid, sizeof(hpid));
  610. /* CHECK:  This may prevent restoration */
  611. #ifdef TOS
  612.     mread(fd, (genericptr_t) &tlev, sizeof(tlev));
  613.     dlvl=tlev&0x00ff;
  614. #else
  615.     mread(fd, (genericptr_t) &dlvl, sizeof(dlvl));
  616. #endif
  617.     if((pid && pid != hpid) || (lev && dlvl != lev)) {
  618. #ifdef WIZARD
  619.         if (wizard) {
  620.             if (pid && pid != hpid)
  621.                 pline("PID (%d) doesn't match saved PID (%d)!", hpid, pid);
  622.             else if (lev && dlvl != lev)
  623.                 pline("This is level %d, not %d!", dlvl, lev);
  624.         }
  625. #endif
  626.         trickery();
  627.     }
  628.  
  629. #ifdef RLECOMP
  630.     {
  631.         short    i, j;
  632.         uchar    len;
  633.         struct rm r;
  634.         
  635.         i = 0; j = 0; len = 0;
  636.         while(i < ROWNO) {
  637.             while(j < COLNO) {
  638.             if(len > 0) {
  639.                 levl[j][i] = r;
  640.                 len -= 1;
  641.                 j += 1;
  642.             } else {
  643.                 mread(fd, (genericptr_t)&len, sizeof(uchar));
  644.                 mread(fd, (genericptr_t)&r, sizeof(struct rm));
  645.             }
  646.             }
  647.             j = 0;
  648.             i += 1;
  649.         }
  650.     }
  651. #else
  652.     mread(fd, (genericptr_t) levl, sizeof(levl));
  653. #endif    /* RLECOMP */
  654.  
  655.     mread(fd, (genericptr_t)&omoves, sizeof(omoves));
  656.     mread(fd, (genericptr_t)&upstair, sizeof(stairway));
  657.     mread(fd, (genericptr_t)&dnstair, sizeof(stairway));
  658.     mread(fd, (genericptr_t)&upladder, sizeof(stairway));
  659.     mread(fd, (genericptr_t)&dnladder, sizeof(stairway));
  660.     mread(fd, (genericptr_t)&sstairs, sizeof(stairway));
  661.     mread(fd, (genericptr_t)&updest, sizeof(dest_area));
  662.     mread(fd, (genericptr_t)&dndest, sizeof(dest_area));
  663.     mread(fd, (genericptr_t)&level.flags, sizeof(level.flags));
  664.  
  665.     fmon = restmonchn(fd, ghostly);
  666.  
  667.     /* regenerate animals while on another level */
  668.     { long tmoves = (monstermoves > omoves) ? monstermoves-omoves : 0;
  669.       register struct monst *mtmp2;
  670.  
  671.       for(mtmp = fmon; mtmp; mtmp = mtmp2) {
  672.         mtmp2 = mtmp->nmon;
  673.         if(mtmp->data->geno & G_GENOD) {
  674.             /* mondead() would try to link the monster's objects
  675.              * into fobj and the appropriate nexthere chain.
  676.              * unfortunately, such things will not have sane
  677.              * values until after find_lev_obj() well below
  678.              * here, so we'd go chasing random pointers if we
  679.              * tried that.  we could save the monster's objects
  680.              * in another chain and insert them in the level
  681.              * later, but that's a lot of work for very little
  682.              * gain.  hence, just throw the objects away via
  683.              * mongone() and pretend the monster wandered off
  684.              * somewhere private before the genocide.
  685.              */
  686.             mongone(mtmp);
  687.             continue;
  688.         }
  689.  
  690.         if (ghostly) {
  691.             /* reset peaceful/malign relative to new character */
  692.             if(!mtmp->isshk)
  693.                 /* shopkeepers will reset based on name */
  694.                 mtmp->mpeaceful = peace_minded(mtmp->data);
  695.             set_malign(mtmp);
  696.         } else if (mtmp->mtame && tmoves > 250)
  697.             mtmp->mtame = mtmp->mpeaceful = 0;
  698.  
  699.         /* restore shape changers - Maarten Jan Huisjes */
  700.         if (mtmp->data == &mons[PM_CHAMELEON]
  701.             && !Protection_from_shape_changers
  702.             && !mtmp->cham)
  703.             mtmp->cham = 1;
  704.         else if(Protection_from_shape_changers) {
  705.             if (mtmp->cham) {
  706.                 mtmp->cham = 0;
  707.                 (void) newcham(mtmp, &mons[PM_CHAMELEON]);
  708.             } else if(is_were(mtmp->data) && !is_human(mtmp->data))
  709.                 new_were(mtmp);
  710.         }
  711.  
  712.         if (!ghostly) {
  713.             long nhp = mtmp->mhp +
  714.                 (regenerates(mtmp->data) ? tmoves : tmoves/20);
  715.  
  716.             if(!mtmp->mcansee && mtmp->mblinded) {
  717.                 if ((long) mtmp->mblinded <= tmoves) {
  718.                     mtmp->mblinded = 0;
  719.                     mtmp->mcansee = 1;
  720.                 } else mtmp->mblinded -= tmoves;
  721.             }
  722.             if(!mtmp->mcanmove && mtmp->mfrozen) {
  723.                 if ((long) mtmp->mfrozen <= tmoves) {
  724.                     mtmp->mfrozen = 0;
  725.                     mtmp->mcanmove = 1;
  726.                 } else mtmp->mfrozen -= tmoves;
  727.             }
  728.             if(mtmp->mflee && mtmp->mfleetim) {
  729.                 if ((long) mtmp->mfleetim <= tmoves) {
  730.                     mtmp->mfleetim = 0;
  731.                     mtmp->mflee = 0;
  732.                 } else mtmp->mfleetim -= tmoves;
  733.             }
  734.             if(nhp >= mtmp->mhpmax)
  735.                 mtmp->mhp = mtmp->mhpmax;
  736.             else
  737.                 mtmp->mhp = nhp;
  738.         }
  739.       }
  740.     }
  741.  
  742.     rest_worm(fd);    /* restore worm information */
  743.     ftrap = 0;
  744.     while (trap = newtrap(),
  745.            mread(fd, (genericptr_t)trap, sizeof(struct trap)),
  746.            trap->tx) {
  747.         trap->ntrap = ftrap;
  748.         ftrap = trap;
  749.     }
  750.     dealloc_trap(trap);
  751.     fobj = restobjchn(fd, ghostly);
  752.     find_lev_obj();
  753.     billobjs = restobjchn(fd, ghostly);
  754.     rest_engravings(fd);
  755.     rest_rooms(fd);        /* No joke :-) */
  756.     mread(fd, (genericptr_t)doors, sizeof(doors));
  757.  
  758.     /* reset level.monsters for new level */
  759.     for (x = 0; x < COLNO; x++)
  760.         for (y = 0; y < ROWNO; y++)
  761.         level.monsters[x][y] = (struct monst *) 0;
  762.     for (mtmp = level.monlist; mtmp; mtmp = mtmp->nmon) {
  763.         if (mtmp->isshk)
  764.         set_residency(mtmp, FALSE);
  765.         place_monster(mtmp, mtmp->mx, mtmp->my);
  766.         if (mtmp->wormno) place_wsegs(mtmp);
  767.     }
  768.     restdamage(fd, ghostly);
  769.  
  770.  
  771. #ifdef TUTTI_FRUTTI
  772.     /* Now get rid of all the temp fruits... */
  773.     if (ghostly) {
  774.         struct fruit *fruit;
  775.  
  776.         while(oldfruit) {
  777.             fruit = oldfruit->nextf;
  778.             dealloc_fruit(oldfruit);
  779.             oldfruit = fruit;
  780.         }
  781.     }
  782. #endif
  783.     if (ghostly && lev > ledger_no(&medusa_level) &&
  784.             lev < ledger_no(&stronghold_level) && xdnstair == 0) {
  785.         coord cc;
  786.  
  787.         mazexy(&cc);
  788.         xdnstair = cc.x;
  789.         ydnstair = cc.y;
  790.         levl[cc.x][cc.y].typ = STAIRS;
  791.     }
  792.     if (ghostly && (br = Is_branchlev(&u.uz)) && u.uz.dlevel == 1) {
  793.         d_level ltmp;
  794.  
  795.         if (on_level(&u.uz, &br->end1))
  796.         assign_level(<mp, &br->end2);
  797.         else
  798.         assign_level(<mp, &br->end1);
  799.  
  800.         switch(br->type) {
  801.         case BR_STAIR:
  802.         case BR_NO_END1:
  803.         case BR_NO_END2: /* OK to assign to sstairs if it's not used */
  804.         assign_level(&sstairs.tolev, <mp);
  805.         break;        
  806.         case BR_PORTAL: /* max of 1 portal per level */
  807.         {
  808.             register struct trap *ttmp;
  809.             for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
  810.             if (ttmp->ttyp == MAGIC_PORTAL)
  811.                 break;
  812.             if (!ttmp) panic("getlev: need portal but none found");
  813.             assign_level(&ttmp->dst, <mp);
  814.         }
  815.         break;
  816.         }
  817.     }
  818. }
  819.  
  820. #ifdef ZEROCOMP
  821. #define RLESC '\0'    /* Leading character for run of RLESC's */
  822.  
  823. #ifndef ZEROCOMP_BUFSIZ
  824. #define ZEROCOMP_BUFSIZ BUFSZ
  825. #endif
  826. static unsigned char NEARDATA inbuf[ZEROCOMP_BUFSIZ];
  827. static unsigned short NEARDATA inbufp = 0;
  828. static unsigned short NEARDATA inbufsz = 0;
  829. static short NEARDATA inrunlength = -1;
  830. static int NEARDATA mreadfd;
  831.  
  832. static int
  833. mgetc()
  834. {
  835.     if (inbufp >= inbufsz) {
  836.     inbufsz = read(mreadfd, (genericptr_t)inbuf, sizeof inbuf);
  837.     if (!inbufsz) {
  838.         if (inbufp > sizeof inbuf)
  839.         error("EOF on file #%d.\n", mreadfd);
  840.         inbufp = 1 + sizeof inbuf;  /* exactly one warning :-) */
  841.         return -1;
  842.     }
  843.     inbufp = 0;
  844.     }
  845.     return inbuf[inbufp++];
  846. }
  847.  
  848. void
  849. minit()
  850. {
  851.     inbufsz = 0;
  852.     inbufp = 0;
  853.     inrunlength = -1;
  854. }
  855.  
  856. int
  857. mread(fd, buf, len)
  858. int fd;
  859. genericptr_t buf;
  860. register unsigned len;
  861. {
  862.     /*register int readlen = 0;*/
  863.     mreadfd = fd;
  864.     while (len--) {
  865.     if (inrunlength > 0) {
  866.         inrunlength--;
  867.         *(*((char **)&buf))++ = '\0';
  868.     } else {
  869.         register short ch = mgetc();
  870.         if (ch < 0) return -1; /*readlen;*/
  871.         if ((*(*(char **)&buf)++ = ch) == RLESC) {
  872.         inrunlength = mgetc();
  873.         }
  874.     }
  875.     /*readlen++;*/
  876.     }
  877.     return 0; /*readlen;*/
  878. }
  879.  
  880. #else /* ZEROCOMP */
  881.  
  882. void
  883. minit()
  884. {
  885.     return;
  886. }
  887.  
  888. void
  889. mread(fd, buf, len)
  890. register int fd;
  891. register genericptr_t buf;
  892. register unsigned int len;
  893. {
  894.     register int rlen;
  895.  
  896. #if defined(BSD) || defined(ULTRIX)
  897.     rlen = read(fd, buf, (int) len);
  898.     if(rlen != len){
  899. #else /* e.g. SYSV, __TURBOC__ */
  900.     rlen = read(fd, buf, (unsigned) len);
  901.     if((unsigned)rlen != len){
  902. #endif
  903.         pline("Read %d instead of %u bytes.", rlen, len);
  904.         if(restoring) {
  905.             (void) close(fd);
  906.             (void) delete_savefile();
  907.             error("Error restoring old game.");
  908.         }
  909.         panic("Error reading level file.");
  910.     }
  911. }
  912. #endif /* ZEROCOMP */
  913.  
  914. /*restore.c*/
  915.